home *** CD-ROM | disk | FTP | other *** search
/ CGI How-To / CGI HOW-TO.iso / java / mult_j / cgi.jav next >
Encoding:
Text File  |  1996-06-15  |  10.4 KB  |  524 lines

  1. import java.util.*;
  2. import java.io.*;
  3.  
  4. public class Cgi extends Object
  5. {
  6.  
  7.     public static boolean needsEncode(char x)
  8.     {
  9.         return !(Character.isDigit(x)||Character.isUpperCase(x)
  10.                 ||Character.isLowerCase(x)||(x==' '));
  11.     }
  12.  
  13.     public static String decodeCGIData(String queryString)
  14.     {
  15.         StringBuffer tmp = new StringBuffer(queryString);
  16.         decodeData(tmp);
  17.         return tmp.toString();
  18.     }
  19.  
  20.     public static void decodeData(StringBuffer queryString)
  21.     {
  22.         /* Temporary variables */
  23.         int i = 0, j = 0, max = 0;
  24.         char c;
  25.     
  26.         /*
  27.         * Loop over the string.
  28.         * We use two loop indices,
  29.         * i is the actual current character
  30.         * j is used to move ahead when hex codes are found
  31.         * Two indices are needed since the string shrinks
  32.         * as hex-codes are turned into single characters.
  33.         */
  34.         if(queryString != null) max = queryString.length();
  35.     
  36.         for (i=0, j=0; j < max; ++i, ++j) 
  37.         {
  38.             /* If we have found hex-codes, j>i so copy the data down. */
  39.         
  40.             queryString.setCharAt(i,queryString.charAt(j));
  41.         
  42.             if ('+' == queryString.charAt(i)) /* Convert pluses to spaces */
  43.             {
  44.                 queryString.setCharAt(i,' ');
  45.             }
  46.             else if ('%' == queryString.charAt(j))/* Convert hex codes */
  47.             {
  48.                 /*
  49.                 * Get the first number of the hex code, and store it
  50.                 * as a char.
  51.                 */
  52.             
  53.                 c = (char)(((queryString.charAt(j+1) >= 'A') ?
  54.                             ((queryString.charAt(j+1) & 0xdf) - 'A') + 10 
  55.                             : (queryString.charAt(j+1) - '0')));
  56.                 /*
  57.                 * The first hex-code was the 16 places, so multiply
  58.                 * c by 16.
  59.                 */
  60.                             
  61.                 c *= 16;
  62.             
  63.                 /*
  64.                 * Get the second number in the hex code and add that
  65.                 * to the value of c.
  66.                 * c now stores the correct character for the hex code.
  67.                 */
  68.                 c += (char)(((queryString.charAt(j+2) >= 'A') ? 
  69.                             ((queryString.charAt(j+2) & 0xdf) - 'A') + 10 
  70.                             : (queryString.charAt(j+2) - '0')));
  71.                             
  72.                 /* Replace the % char we copied with the actual character. */                
  73.                 queryString.setCharAt(i,c);
  74.     
  75.                 /* Move j past the hex-code */
  76.                 j += 2;
  77.             }
  78.         }
  79.         
  80.         /* Truncate the string to remove trailing characters */
  81.         queryString.setLength(i);
  82.     }
  83.  
  84.     public static String encodeCGIData(String aString)
  85.     {
  86.         StringBuffer tmp = new StringBuffer(aString);
  87.         encodeData(tmp);
  88.         return tmp.toString();
  89.     }
  90.  
  91.     /* encodeData() encodes a string for CGI */
  92.     public static void encodeData(StringBuffer aString)
  93.     {
  94.         int i,size,l,push = 0;
  95.  
  96.         if(aString.length() != 0)
  97.         {
  98.  
  99.             /* figure out the size after encoding */
  100.             l=aString.length();
  101.  
  102.             for(i=0;i<l;i++)
  103.             {
  104.                 if(Cgi.needsEncode(aString.charAt(i)))
  105.                 {
  106.                     push+=2;
  107.                 }
  108.             }
  109.  
  110.             /* If we encountered characters to encode, encode them */
  111.             if(push != 0)
  112.             {
  113.                 /* Grow as needed */
  114.                 aString.setLength(l+push);
  115.  
  116.                 /* Start encoded, back to front to reduce copying */
  117.                 for(i=l-1;i>=0;i--)
  118.                 {
  119.                       if(Cgi.needsEncode(aString.charAt(i)))
  120.                       {
  121.                         int tmp;
  122.  
  123.                         tmp = (aString.charAt(i))%16;
  124.                         aString.setCharAt(i+push,(char)((tmp>=10)? (tmp-10 + 'A') : (tmp+'0')));
  125.                         push--;
  126.  
  127.                         tmp = (aString.charAt(i))/16;
  128.                         aString.setCharAt(i+push,(char)((tmp>=10)? (tmp-10 + 'A') : (tmp+'0')));
  129.  
  130.                         push--;
  131.                         aString.setCharAt(i+push,'%');
  132.                     }
  133.                     else/*push the other char back*/
  134.                     {
  135.                           aString.setCharAt(i+push,aString.charAt(i));
  136.                     }
  137.                 }
  138.             }
  139.  
  140.             l=aString.length();
  141.             /*Convert the spaces to pluses */
  142.             for(i=0;i<l;i++)
  143.             {
  144.                 if(aString.charAt(i) == ' ') aString.setCharAt(i,'+');
  145.             }
  146.  
  147.         } 
  148.     }
  149.  
  150.     /* 
  151.      * encodeDictionary() encodes a dictionary in the form
  152.      * of CGI data.
  153.      */
  154.     public static String encodeDictionary(Hashtable dataDict)
  155.     {
  156.         StringBuffer returnString;
  157.         Enumeration state;
  158.         String key;
  159.         Object value;
  160.         StringBuffer buffer;
  161.         boolean needAmp = false;
  162.  
  163.         /* allocate the string */
  164.         returnString =new StringBuffer();
  165.         buffer =new StringBuffer();
  166.  
  167.         /* Create a dictionary state */
  168.         state = dataDict.keys();
  169.  
  170.         /* Calculate how long the string will be */
  171.  
  172.         while(state.hasMoreElements())
  173.         {
  174.             key = (String) state.nextElement();
  175.  
  176.             /* If this isn't a multiple value, encode and append it */
  177.             if((key.length()!=0) && (key.charAt(0) != 'A') 
  178.                                 && (key.charAt(1)!='_'))
  179.             {
  180.                 value = dataDict.get(key);
  181.     
  182.                 buffer.setLength(0);
  183.                 buffer.append(key);
  184.                 encodeData(buffer);
  185.  
  186.                 if(needAmp)
  187.                 {
  188.                     returnString.append('&');
  189.                 }
  190.  
  191.                 returnString.append(buffer);
  192.                 returnString.append('=');
  193.  
  194.                 if(value!=null)
  195.                 {
  196.                     buffer.setLength(0);
  197.                     buffer.append((String)value);
  198.                     encodeData(buffer);
  199.                 }
  200.                 else
  201.                 {
  202.                     buffer.setLength(0);
  203.                 }
  204.  
  205.                 returnString.append(buffer);
  206.  
  207.                 needAmp = true;
  208.             }
  209.         }
  210.  
  211.         return returnString.toString();
  212.     }
  213.  
  214.     public static Hashtable parseData(String queryString)
  215.     {
  216.         /* Temporary variables */
  217.         StringTokenizer cursor;
  218.         String key,value;
  219.         Hashtable dataDict = new Hashtable();
  220.  
  221.         cursor = new StringTokenizer(queryString,"&=",true);
  222.  
  223.         while(cursor.hasMoreElements())
  224.         {
  225.  
  226.             key = null;/* Reset the tmp key */
  227.  
  228.             value = null;/* Reset the tmp value */
  229.  
  230.             key = cursor.nextToken();
  231.  
  232.             /* If we have a key, try to read the value */
  233.  
  234.             if( key != null)
  235.             {
  236.  
  237.                 /*
  238.                 * See if the next character is a &,
  239.                 * if it is the key has an empty value.
  240.                 */
  241.  
  242.                 if(cursor.hasMoreElements()&&
  243.                     (cursor.nextToken().equals("=")))
  244.                 {
  245.                     value = cursor.nextToken();
  246.                     if(cursor.hasMoreElements())
  247.                         cursor.nextToken();//Get rid of seperator
  248.  
  249.                     /*
  250.                     * Decode the key and value
  251.                     */
  252.  
  253.                     key = decodeCGIData(key);
  254.                     value = decodeCGIData(value);
  255.                 }
  256.                 else/* Key has an empty value */
  257.                 {
  258.                     /*
  259.                     * Decode the key, then
  260.                     * print the key and an empty value
  261.                     */
  262.                     if(cursor.hasMoreElements())
  263.                         cursor.nextToken();//Get rid of seperator
  264.  
  265.                     key = decodeCGIData(key);
  266.  
  267.                     value = new String("");
  268.                 }
  269.  
  270.                 /*
  271.                 * Insert the value into the dictionary, but
  272.                 * allow for multiple values on key.
  273.                 * Put multiple values into an Array, with the key,
  274.                 * A_key.
  275.                 */
  276.  
  277.                 /* Check if this is a multiple value */
  278.                 if((dataDict.get(key)) != null)
  279.                 {
  280.                     /* Create the name for the array key */
  281.                     String aName;
  282.  
  283.                     aName = "A_"+key;
  284.  
  285.                     /* Check if the array is in the dict, already */
  286.  
  287.                     if((dataDict.get(aName))!=null)
  288.                     {
  289.                         /* Add the new value to the array */
  290.                         Vector theArray;
  291.  
  292.                         theArray = (Vector) dataDict.get(aName);
  293.  
  294.                         theArray.addElement(value);
  295.  
  296.                         /* Set the dictionaries value, to the latest */
  297.  
  298.                         dataDict.put(key, value);
  299.                     }
  300.                     else /* If not, ... */
  301.                     {
  302.                         /* Create the array */
  303.                         Vector theArray = null;
  304.                         theArray = new Vector();
  305.  
  306.                         /* Add the first value to the array */
  307.                         theArray.addElement(dataDict.get(key));
  308.                         
  309.                         /* Add the new value to the array */
  310.                         theArray.addElement(value);
  311.  
  312.                         /* Set the dictionaries value, to the latest */
  313.                         dataDict.put(key, value);
  314.  
  315.                         /* Add the array to the dictionary */
  316.                         dataDict.put(aName,theArray);
  317.                     }
  318.                 }
  319.                 else /* If not, simple insert the value */
  320.                 {
  321.                     dataDict.put(key, value);
  322.                 }
  323.  
  324.             }
  325.  
  326.         }
  327.         
  328.         return dataDict;
  329.     }
  330.  
  331.     public static String readGetData()
  332.     {
  333.         String queryString;
  334.         queryString = System.getProperty("QUERY_STRING");
  335.         
  336.         if(queryString == null)
  337.         {
  338.             queryString = new String("");
  339.         }
  340.         
  341.         return queryString;
  342.     }
  343.     
  344.     public static String  readPostData()
  345.     {
  346.         /* The data after it is read in */
  347.         String queryString;
  348.     
  349.         /* The amount of data to read */
  350.         int contentLength,i;
  351.  
  352.         /* Temporary variables for storing envvar and reading*/
  353.         String sizeString;
  354.         byte data[] = null;
  355.     
  356.         /* Read the environment variable CONTENT_LENGTH */
  357.     
  358.         sizeString = System.getProperty("CONTENT_LENGTH");
  359.     
  360.     
  361.         /* If the env. var. existed, convert the string to an integer */
  362.     
  363.         if (sizeString!=null)
  364.         {
  365.             contentLength = Integer.parseInt( sizeString );
  366.             data = new byte[contentLength];
  367.         }
  368.         else
  369.         {
  370.             contentLength = 0;
  371.         }
  372.     
  373.         if ( data != null)
  374.         {
  375.             i = 0;
  376.             
  377.             try
  378.             {
  379.                 while( i < contentLength)
  380.                 {
  381.                         data[ i++ ] = (byte) System.in.read();
  382.                 }
  383.             }
  384.             catch(IOException exp)
  385.             {
  386.                 data = null;
  387.             }
  388.             /* Set the arguement to point to the data. */
  389.  
  390.             if(data != null) queryString = new String(data,0);
  391.             else queryString = new String("");
  392.  
  393.         }
  394.         else
  395.         {
  396.             queryString = new String("");
  397.         }
  398.         
  399.         return queryString;
  400.     }
  401.  
  402.     public static String readData()
  403.     {
  404.         String requestType = null;
  405.         String retVal = null;
  406.     
  407.     
  408.         /* Read the request type */
  409.     
  410.         requestType = System.getProperty("REQUEST_METHOD");
  411.     
  412.         /*
  413.          * If it is a GET request use readGetData,
  414.          * otherwise, if it is a POST request, use readPostData.
  415.          */
  416.      
  417.         if((requestType != null) && requestType.equals("GET"))
  418.         {
  419.             retVal = readGetData();
  420.         }
  421.         else if((requestType != null) && requestType.equals("POST"))
  422.         {
  423.             retVal = readPostData();
  424.         }
  425.         else
  426.         {
  427.              retVal = new String("");
  428.         }
  429.         
  430.         return retVal;
  431.     }
  432.  
  433.     public static Hashtable readParse()
  434.     {
  435.         Hashtable returnData = null;
  436.         String data;
  437.       
  438.          data = readData();
  439.           
  440.         if(data!=null) returnData = parseData(data);
  441.     
  442.         return returnData;
  443.     }
  444.     
  445.     public static void main(String argv[])
  446.     {
  447.           FileInputStream raw;
  448.           DataInputStream input;
  449.           String key,value;
  450.           String curLine;
  451.           Hashtable data,decodedData;
  452.          String encodedData;
  453.           Enumeration cursor;
  454.           int matches,total,ind;
  455.  
  456.           if(argv.length > 0)
  457.         {
  458.             try
  459.             {
  460.                 raw = new FileInputStream(argv[0]);
  461.                 input = new DataInputStream(raw);
  462.                 data = new Hashtable();
  463.                 
  464.                 while(input.available() != 0)
  465.                 {
  466.                     curLine = input.readLine();
  467.                     ind = curLine.indexOf(' ');
  468.                     
  469.                     key = curLine.substring(0,ind);
  470.                     value = curLine.substring(ind+1);
  471.                     data.put(key,value);
  472.                 }
  473.  
  474.                 encodedData = encodeDictionary(data);
  475.                 decodedData = parseData(encodedData);
  476.                 
  477.                 cursor = data.keys();
  478.                 matches = 0;
  479.                 total = 0;
  480.  
  481.                 while(cursor.hasMoreElements())
  482.                 {
  483.                     key = (String)cursor.nextElement();
  484.                     value = (String)decodedData.get(key);
  485.                     
  486.                     if(data.get(key).equals(value))
  487.                     {
  488.                         matches++;
  489.                         System.out.println(data.get(key) + " = " + value);
  490.                     }
  491.                     else
  492.                     {
  493.                         System.out.println(data.get(key) + " != " + value);
  494.                     }
  495.                     total++;
  496.                 }
  497.  
  498.                 if(matches == total)
  499.                 {
  500.                     System.out.println("Test succeeded.");
  501.                 }
  502.                 else
  503.                 {
  504.                     System.out.println("Test failed.");
  505.                 }
  506.  
  507.  
  508.                 input.close();
  509.                 raw.close();
  510.             }
  511.             catch(IOException exp)
  512.             {
  513.                 System.out.println("Encountered IO exception!");
  514.             }
  515.         }
  516.         else
  517.         {
  518.             System.out.println("usage: java Cgi filename");
  519.             System.out.println("The file should have space seperated keys and values\n");
  520.         }
  521.     }
  522.  
  523. }
  524.